<?php
    if (!defined('ZT')) exit;
    
    class Imagen {        
        static function abre($ruta)
        {
            $datos = getimagesize($ruta, $datos);
                
            if ($datos) {
                return new ZT_Imagen($ruta, $datos);
            }
        }
        
        static function abre_manipulable($ruta)
        {
            $datos = self::abre($ruta);
            
            if ($datos) {
            	$extension = $datos->extension( );
            	
                if (function_exists("imagecreatefrom$extension")) {
                    return new ZT_ImagenManipulable($datos);
                }
            }
        }
        
        static function crea_buffer($w, $h)
        {
            return new ZT_BufferImagen(imagecreatetruecolor($w, $h), array($w, $h));
        }
        
        static function crea_buffer_inteligente($w, $h, $calidad = 2)
        {
            return new ZT_BufferInteligenteImagen(imagecreatetruecolor($w, $h), array($w, $h), $calidad);
        }
        
        static function func_guarda($extension)
        {
            $extension = image_type_to_extension($extension, false);
            $func_guarda = "image$extension";
            
            if (!function_exists($func_guarda)) {
                throw new Exception("Funcion serializadora de $extension no disponible");
            }
            
            return $func_guarda;
        }
        
        static function crea_thumbnail($buffer_origen, $buffer_destino, $ruta_destino, $func_guarda)
        {        
            self::crea_thumbnail_impl($buffer_origen, $buffer_destino, $ruta_destino, $func_guarda, 0, 0, $buffer_origen->ancho( ), $buffer_origen->alto( ));
        }
        
        static function crea_thumbnail_seleccion($buffer_origen, $buffer_destino, $ruta_destino, $func_guarda, $x1, $x2, $y1, $y2)
        {        
            self::crea_thumbnail_impl($buffer_origen, $buffer_destino, $ruta_destino, $func_guarda, $x1, $y1, $x2 - $x1, $y2 - $y1);
        }
        
        static function pon_marca_agua($buffer_origen, $buffer_marca, $ruta_destino, $func_guarda)
        {
        	$origen = $buffer_origen->memoria( );
            $marca_x = $buffer_marca->ancho( );
            $marca_y = $buffer_marca->alto( );

            imagecopy($origen, $buffer_marca->memoria( ), $buffer_origen->ancho( ) - $marca_x - 15, $buffer_origen->alto( ) - $marca_y - 15, 0, 0, $marca_x, $marca_y); 
            $func_guarda($origen, $ruta_destino);            
            
            chmod($ruta_destino, 0644);
        }
        
        private static function crea_thumbnail_impl($buffer_origen, $buffer_destino, $ruta_destino, $func_guarda, $x, $y, $ow, $oh)
        {
        	$nw = $buffer_destino->ancho( );
        	$nh = $buffer_destino->alto( );
            
            $propw = $ow / $nw;
            $proph = $oh / $nh;
            
            if ($propw < $proph) {
                $hipotetico = $nh * $propw;
                $desplazamiento = ($oh - $hipotetico) / 2;
                
                $buffer_destino->copia_desde($buffer_origen->memoria( ), 0, 0, $x, $y + $desplazamiento, $ow, $hipotetico);
            }
            else {
                $hipotetico = $nw * $proph;
                $desplazamiento = ($ow - $hipotetico) / 2;
                
                $buffer_destino->copia_desde($buffer_origen->memoria( ), 0, 0, $x + $desplazamiento, $y, $hipotetico, $oh);
            }

            $func_guarda($buffer_destino->memoria( ), $ruta_destino);            
            chmod($ruta_destino, 0644);
        }
    }
    
    class ZT_Imagen {
        protected $ruta;
        protected $datos;

        function __construct($ruta, $datos)
        {
            $datos[2] = image_type_to_extension($datos[2], false);

            $this->ruta = $ruta;
            $this->datos = $datos;
        }

        function ancho( )
        {
            return $this->datos[0];
        }
        
        function alto( )
        {
        	return $this->datos[1];
        }
        
        function ruta( )
        {
            return $this->ruta;
        }
        
        function extension( )
        {
        	return $this->datos[2];
        }
        
        function __toString( )
        {
            return $this->ruta;
        }
    }
    
    class ZT_ImagenManipulable extends ZT_Imagen {
        function __construct($datos_imagen)
        {
            $this->ruta = $datos_imagen->ruta;
            $this->datos = $datos_imagen->datos;
        }
        
        function lee_imagen( )
        {
            $func_crea = "imagecreatefrom{$this->datos[2]}";
            return new ZT_BufferImagen($func_crea($this->ruta), $this->datos);
        }
    }
    
    class ZT_BufferImagen {
        protected $memoria;
        protected $datos;
    
        function __construct($memoria, $datos)
        {
            $this->memoria = $memoria;
            $this->datos = $datos;
        }
                
        function ancho( )
        {
            return $this->datos[0];
        }
        
        function alto( )
        {
        	return $this->datos[1];
        }

        function memoria( )
        {
            return $this->memoria;
        }
        
        function copia_desde($origen, $xn, $yn, $xo, $yo, $ow, $oh)
        {
			imagecopyresampled($this->memoria, $origen, $xn, $yn, $xo, $yo, $this->datos[0], $this->datos[1], $ow, $oh);
        }
    }
    
    class ZT_BufferInteligenteImagen extends ZT_BufferImagen {
    	private $nw_proceso;
        private $nh_proceso;
    	private $memoria_proceso;
    	
        function __construct($memoria, $datos, $calidad)
        {
            parent::__construct($memoria, $datos);
            
            $this->nw_proceso = $this->datos[0] * $calidad;
            $this->nh_proceso = $this->datos[1] * $calidad;
        }
        
        function copia_desde($origen, $xn, $yn, $xo, $yo, $ow, $oh)
        {
			if ($this->nw_proceso > $ow && $this->nh_proceso > $oh) {
                parent::copia_desde($origen, $xn, $yn, $xo, $yo, $ow, $oh);
            }
            else {
                $nw_proceso_temp = $this->nw_proceso + 1;
                $nh_proceso_temp = $this->nh_proceso + 1;
            
                if (!isset($this->memoria_proceso)) {
                    $this->memoria_proceso = imagecreatetruecolor($nw_proceso_temp, $nh_proceso_temp);
                }
            
			    imagecopyresized($this->memoria_proceso, $origen, 0, 0, $xo, $yo, $nw_proceso_temp, $nh_proceso_temp, $ow, $oh);
			    imagecopyresampled($this->memoria, $this->memoria_proceso, $xn, $yn, 0, 0, $this->datos[0], $this->datos[1], $this->nw_proceso, $this->nh_proceso);
		  	}
        }
    }
?>